// XFile.cpp

#include "stdafx.h"

#include "DXFile.h"
#include "rmxftmpl.h"
#include "D3D9Device.h"

#include <stdio.h>

#include "XFile.h"

//////////////////////////////////////////////////////////////////////////
CXFile::CXFile(void)
{

}

CXFile::~CXFile()
{

}

//////////////////////////////////////////////////////////////////////////
bool CXFile::Load(const char* pszFileName)
{
	if (!pszFileName || strlen(pszFileName) == 0)
	{
		return false;
	}

	ID3DXFile* pFile = NULL;
	if (FAILED(D3DXFileCreate(&pFile)))
	{
		return false;
	}

	// register standard template
	if (FAILED(pFile->RegisterTemplates((LPVOID)D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES)))
	{
		pFile->Release();
		return false;
	}

	ID3DXFileEnumObject* pFileEnum = NULL;
	if (FAILED(pFile->CreateEnumObject((LPVOID)pszFileName, DXFILELOAD_FROMFILE, &pFileEnum)))
	{
		
		pFile->Release();
		return false;
	}

	SIZE_T nNumChild, i;
	pFileEnum->GetChildren(&nNumChild);

	for (i = 0; i < nNumChild; ++i)
	{
		ID3DXFileData* pFileData  = NULL;
		pFileEnum->GetChild(i, &pFileData);

		bool bResult = this->GetObject(pFileData, NULL, 0, 0, false);
		if (pFileData)
		{
			pFileData->Release();
			pFileData = NULL;
		}

		if (!bResult)
		{
			break;
		}
	}

	if (pFileEnum)
	{
		pFileEnum->Release();
		pFileEnum = NULL;
	}

	if (pFile)
	{
		pFile->Release();
		pFile = NULL;
	}

	return true;
}

//////////////////////////////////////////////////////////////////////////
bool CXFile::GetObject(ID3DXFileData *pFileData, ID3DXFileData *pParentFileData, DWORD dwDepth, void **pData, bool bForceRef)
{
	return GetChildObject(pFileData, dwDepth, pData, bForceRef);
}

bool CXFile::GetChildObject(ID3DXFileData *pFileData, DWORD dwDepth, void **pData, bool bForceRef)
{
	SIZE_T nNumChild;
	pFileData->GetChildren(&nNumChild);

	SIZE_T i = 0;
	for(; i < nNumChild; ++i)
	{
		ID3DXFileData* pChildFileData = NULL;
		pFileData->GetChild(i, &pChildFileData);

		if(pChildFileData->IsReference())
		{
			bForceRef = true;
		}

		bool bResult = this->GetObject(pChildFileData, pFileData, dwDepth + 1, pData, bForceRef);
		if (pChildFileData)
		{
			pChildFileData->Release();
			pChildFileData = NULL;
		}

		if(bResult == false)	// parsing failure
		{
			return false;
		}
	}	

	return true;
}

void CXFile::GetObjectGUID(ID3DXFileData *pFileData, GUID *type) const
{
	if (NULL == pFileData)
	{
		type = NULL;
		return;
	}

	pFileData->GetType(type);
}

const char* CXFile::GetObjectName(ID3DXFileData *pFileData) const
{
	if (NULL == pFileData)
	{
		return NULL;
	}

	DWORD dwSize = 0;
	pFileData->GetName(NULL, &dwSize);

	char* pszName = NULL;
	if (dwSize)
	{
		pszName = new char[dwSize];
		pFileData->GetName(pszName, &dwSize);
	}

	return pszName;
}